// addrspace.cc 
//	Routines to manage address spaces (executing user programs).
//
//	In order to run a user program, you must:
//
//	1. link with the -N -T 0 option 
//	2. run coff2noff to convert the object file to Nachos format
//		(Nachos object code format is essentially just a simpler
//		version of the UNIX executable object code format)
//	3. load the NOFF file into the Nachos file system
//		(if you haven't implemented the file system yet, you
//		don't need to do this last step)
//
// Copyright (c) 1992-1993 The Regents of the University of California.
// All rights reserved.  See copyright.h for copyright notice and limitation 
// of liability and disclaimer of warranty provisions.

#include "copyright.h"
#include "system.h"
#include "addrspace.h"
#include "noff.h"
#include "table.h"
#include "synch.h"
#include "enhancedTranslateEntry.h"
extern "C" { int bzero(char *, int); };

Table::Table(int s) : map(s), table(0), lock(0), size(s) {
    table = new void *[size];
    lock = new Lock("TableLock");
}

Table::~Table() {
    if (table) {
	delete table;
	table = 0;
    }
    if (lock) {
	delete lock;
	lock = 0;
    }
}

void *Table::Get(int i) {
    // Return the element associated with the given if, or 0 if
    // there is none.

    return (i >=0 && i < size && map.Test(i)) ? table[i] : 0;
}

int Table::Put(void *f) {
    // Put the element in the table and return the slot it used.  Use a
    // lock so 2 files don't get the same space.
    int i;	// to find the next slot

    lock->Acquire();
    i = map.Find();
    lock->Release();
    if ( i != -1)
	table[i] = f;
    return i;
}

void *Table::Remove(int i) {
    // Remove the element associated with identifier i from the table,
    // and return it.

    void *f =0;

    if ( i >= 0 && i < size ) {
	lock->Acquire();
	if ( map.Test(i) ) {
	    map.Clear(i);
	    f = table[i];
	    table[i] = 0;
	}
	lock->Release();
    }
    return f;
}

//----------------------------------------------------------------------
// SwapHeader
// 	Do little endian to big endian conversion on the bytes in the 
//	object file header, in case the file was generated on a little
//	endian machine, and we're now running on a big endian machine.
//----------------------------------------------------------------------

static void 
SwapHeader (NoffHeader *noffH)
{
	noffH->noffMagic = WordToHost(noffH->noffMagic);
	noffH->code.size = WordToHost(noffH->code.size);
	noffH->code.virtualAddr = WordToHost(noffH->code.virtualAddr);
	noffH->code.inFileAddr = WordToHost(noffH->code.inFileAddr);
	noffH->initData.size = WordToHost(noffH->initData.size);
	noffH->initData.virtualAddr = WordToHost(noffH->initData.virtualAddr);
	noffH->initData.inFileAddr = WordToHost(noffH->initData.inFileAddr);
	noffH->uninitData.size = WordToHost(noffH->uninitData.size);
	noffH->uninitData.virtualAddr = WordToHost(noffH->uninitData.virtualAddr);
	noffH->uninitData.inFileAddr = WordToHost(noffH->uninitData.inFileAddr);
}

//----------------------------------------------------------------------
// AddrSpace::AddrSpace
// 	Create an address space to run a user program.
//	Load the program from a file "executable", and set everything
//	up so that we can start executing user instructions.
//
//	Assumes that the object code file is in NOFF format.
//
//	"executable" is the file containing the object code to load into memory
//
//      It's possible to fail to fully construct the address space for
//      several reasons, including being unable to allocate memory,
//      and being unable to read key parts of the executable.
//      Incompletely consretucted address spaces have the member
//      constructed set to false.
//----------------------------------------------------------------------

AddrSpace::AddrSpace(OpenFile *executable) : fileTable(MaxOpenFiles) {
	processFile = executable;
	pageTableLock = new Lock("pageTableLock");
	NoffHeader noffH;
    //unsigned int i, size, codeDataSize, stackSize, totalSize;
	unsigned int i;
	// memoryPageID is the physical page gotten from memory manager objects
	int memoryPageID;
	
	// currentValidPage keep tracks of the pages have allocated so far,
	// in case we need to delete them all in the middle of initializing
	// this address space due to NO MORE MEMORY problem.
	// DUE to the counter and PageTable index is used with unsigned int
	// we added another flag to make sure we know what's going on since
	// we can't set currentValidPage to -1
	unsigned int currentValidPage;
	bool currentPageValid;

	// set validProgram to FALSE so we know if the program being loaded is valid
	// or not
	validProgram = FALSE;

	// set validPageTable to FALSE first so we know if we were able to allocate
    // all memory pages needed for this address space
	validPageTable = FALSE;

	// set validPageTable to 0 just to know if we stop before reaching
	// memory allocation section
	currentValidPage = 0;
	currentPageValid = TRUE;

    // Don't allocate the input or output to disk files
    fileTable.Put(0);
    fileTable.Put(0);

    executable->ReadAt((char *)&noffH, sizeof(noffH), 0);
    if ((noffH.noffMagic != NOFFMAGIC) && 
		(WordToHost(noffH.noffMagic) == NOFFMAGIC))
    	SwapHeader(&noffH);

	// instead of ASSERTING, we just return and ask the user to check the flag validProgram
	// so they know if they should delete the AddrSpace, otherwise, it's a valid NACHOS C
	// program and we set the flag to TRUE and start loading into virtual memory
    //ASSERT(noffH.noffMagic == NOFFMAGIC);
	if (noffH.noffMagic != NOFFMAGIC) {
		return;
	}
	else {
		validProgram = TRUE;
	}

    size = noffH.code.size + noffH.initData.size + noffH.uninitData.size;
	codeSize = noffH.code.size;
	programSize = noffH.code.size + noffH.initData.size + noffH.uninitData.size;
	codeDataSize = noffH.code.size + noffH.initData.size;
	stackSize = UserStackSize;
	totalStackSize = UserStackSize * MAX_THREADS;

	//numProgramPages = the total pages needed for code/data/uninitData
	numProgramPages = divRoundUp(size, PageSize);
	//numCodePages = the total pages needed to copy the code/data into memory
	numCodeDataPages = divRoundUp(codeDataSize, PageSize);
	//numStackPages = the number of pages needed for all the treads' stack
	idvStackPages = divRoundUp(UserStackSize, PageSize);
	numStackPages = divRoundUp(UserStackSize, PageSize) * MAX_THREADS;

	//recalculate the stackSize if UserStackSize isn't multiple of PageSize
	stackSize = idvStackPages * PageSize;
	totalStackSize = numStackPages * PageSize;

	//total number pages to be allocated for the process/threads
    numPages = numProgramPages + numStackPages;	// we need to increase the size
						// to leave room for the stack
    totalSize = numPages * PageSize;

	DEBUG('c', "Initializing address space for program...\n");
	DEBUG('c', "Program size: %d, numProgramPages: %d\n", programSize, numProgramPages);
	DEBUG('c', "Code+Data size: %d, numCodeDataPages: %d\n", codeDataSize, numCodeDataPages);
	DEBUG('c', "Individual Stack size: %d, idvStackPages: %d\n", stackSize, idvStackPages);
	DEBUG('c', "Total Stack size: %d, numStackPages: %d\n", totalStackSize, numStackPages);
	DEBUG('c', "Total Memory size: %d, numPages: %d\n", totalSize, numPages);

    ASSERT(numPages <= NumPhysPages);			// check we're not trying
						// to run anything too big --
						// at least until we have
						// virtual memory

	//DEBUG('s', "Initializing address space, num pages %d, size %d, code+data size %d, program size %d\n",
	//				numPages, totalSize, codeDataSize, size);
    //DEBUG('a', "Initializing address space, num pages %d, size %d\n", 
	//				numPages, totalSize);

    
// zero out the entire address space, to zero the unitialized data segment 
// and the stack segment
    //bzero(machine->mainMemory, size);

// then, copy in the code and data segments into memory
/*
    if (noffH.code.size > 0) {
        DEBUG('a', "Initializing code segment, at 0x%x, size %d\n", 
			noffH.code.virtualAddr, noffH.code.size);
        executable->ReadAt(&(machine->mainMemory[noffH.code.virtualAddr]),
			noffH.code.size, noffH.code.inFileAddr);
    }
    if (noffH.initData.size > 0) {
        DEBUG('a', "Initializing data segment, at 0x%x, size %d\n", 
			noffH.initData.virtualAddr, noffH.initData.size);
        executable->ReadAt(&(machine->mainMemory[noffH.initData.virtualAddr]),
			noffH.initData.size, noffH.initData.inFileAddr);
    }
*/

	// first, set up the translation 
    pageTable = new EnhancedTranslateEntry[numPages];

	//memoryMapLock->Acquire();

	//copy the code and data segments of the program into memory, and
	//leave the uninitialized data and stack space on next for loop
    for (i = 0; i < numCodeDataPages; i++) {
		currentValidPage = i;

		pageTable[i].virtualPage = i;	// for now, virtual page # = phys page #
		/*************************************************************/
		/*memoryPageID = memoryMap->Find();
		if (memoryPageID == -1) {
			//memoryMapLock->Release();
			currentPageValid = FALSE;
			printf("[ERROR] NO MORE MEMORY...\n");
			//interrupt->Halt();
			//return;
			break;
		}
	
		pageTable[i].physicalPage = memoryPageID;
		pageTable[i].valid = TRUE;*/
		pageTable[i].valid = FALSE;
		pageTable[i].use = FALSE;
		pageTable[i].dirty = FALSE;
		pageTable[i].readOnly = FALSE;  // if the code segment was entirely on 
		pageTable[i].location = EXECUTABLE;
		pageTable[i].offset = noffH.code.inFileAddr+i*PageSize;
					// a separate page, we could set its 
					// pages to be read-only

		/*******************************Project3 step2 IPT**************************************
		iptLock->Acquire();
		
			
			ipt[pageTable[i].physicalPage].physicalPage = pageTable[i].physicalPage;
			ipt[pageTable[i].physicalPage].virtualPage = pageTable[i].virtualPage;
			ipt[pageTable[i].physicalPage].valid= TRUE;
			ipt[pageTable[i].physicalPage].iptSpace = this;
			//printf("address space : ipt ppn:%d,vpn:%d i:%d \n",ipt[pageTable[i].physicalPage].physicalPage,pageTable[i].virtualPage,i);
			
		iptLock->Release();
	/*******************************end Project3 step2 IPT**********************************/
		//bzero out the current physical memory page
		//bzero(&(machine->mainMemory[PageSize*memoryPageID]), PageSize);

		//copy one PageSize size of data at a time from program to memory
		//if it's the last page, make sure we don't copy anything further than code+data size
		//or we will be copying random data, even though it's not gonna matter for the unitialized
		//data 

		/*
		DEBUG('a', "Initializing code + data segments, at 0x%x, size %d\n", 
					(noffH.code.virtualAddr + i*PageSize), PageSize);
			executable->ReadAt(&(machine->mainMemory[PageSize*memoryPageID]),
					PageSize, (noffH.code.inFileAddr + i*PageSize));
		*/

		// if it's the last page containing data/code, check to see if it takes up full page, if so
		// copy the whole thing, otherwise, copy until the last data byte.
		/*if (i == numCodeDataPages-1) {
			// full page
			if ((codeDataSize % PageSize) == 0) {
				DEBUG('a', "Initializing code + data segments, at 0x%x, size %d\n", 
						(noffH.code.virtualAddr + i*PageSize), PageSize);
				executable->ReadAt(&(machine->mainMemory[PageSize*memoryPageID]),
						PageSize, (noffH.code.inFileAddr + i*PageSize));
			}
			// less than full
			else {
				DEBUG('a', "Initializing code + data segments, at 0x%x, size %d\n", 
						(noffH.code.virtualAddr + i*PageSize), (codeDataSize % PageSize));
				executable->ReadAt(&(machine->mainMemory[PageSize*memoryPageID]),
						(codeDataSize % PageSize), (noffH.code.inFileAddr + i*PageSize));
			}
		}
		else {
			DEBUG('a', "Initializing code + data segments, at 0x%x, size %d\n", 
					(noffH.code.virtualAddr + i*PageSize), PageSize);
			executable->ReadAt(&(machine->mainMemory[PageSize*memoryPageID]),
					PageSize, (noffH.code.inFileAddr + i*PageSize));
		}*/
    }

	// if we were unable to allocate all the pages needed, deallocate all the allocate ones
	/*if (currentPageValid == FALSE) {
		for (i = 0; i < currentValidPage; i++) {
			if (pageTable[i].valid) {
				iptLock->Acquire();
				ipt[pageTable[i].physicalPage].valid= FALSE;
				iptLock->Release();
				memoryMap->Clear(pageTable[i].physicalPage);
				pageTable[i].valid = FALSE;
				
			}
		}

		memoryMapLock->Release();
		return;
	}*/

	//now allocating the remaining memory pages needed for uninitialzed data
	for (i = numCodeDataPages; i < numProgramPages; i++) {
		currentValidPage = i;

		/*pageTable[i].virtualPage = i;

		memoryPageID = memoryMap->Find();
		if (memoryPageID == -1) {
			//memoryMapLock->Release();
			currentPageValid = FALSE;
			printf("[ERROR] NO MORE MEMORY...\n");
			//interrupt->Halt();
			//return;
			break;
		}
	
		pageTable[i].physicalPage = memoryPageID;
		pageTable[i].valid = TRUE;*/
		pageTable[i].valid = FALSE;
		pageTable[i].use = FALSE;
		pageTable[i].dirty = FALSE;
		pageTable[i].readOnly = FALSE;
		pageTable[i].location = NOT_ON_DISK;
		//bzero out the current physical memory page
		/*******************************Project3 step2 IPT**************************************
		iptLock->Acquire();
		
			
			ipt[pageTable[i].physicalPage].physicalPage = pageTable[i].physicalPage;
			ipt[pageTable[i].physicalPage].virtualPage = pageTable[i].virtualPage;
			ipt[pageTable[i].physicalPage].valid= TRUE;
			ipt[pageTable[i].physicalPage].iptSpace = this;
			//printf("address space : ipt ppn:%d,vpn:%d i:%d \n",ipt[pageTable[i].physicalPage].physicalPage,pageTable[i].virtualPage,i);
			
		iptLock->Release();
	/*******************************end Project3 step2 IPT**********************************/
		//bzero(&(machine->mainMemory[PageSize*memoryPageID]), PageSize);
	}

	// same, deallocate the pages we have allocated so far
	/*if (currentPageValid == FALSE) {
		for (i = 0; i < currentValidPage; i++) {
			if (pageTable[i].valid) {
				iptLock->Acquire();
				ipt[pageTable[i].physicalPage].valid= FALSE;
				iptLock->Release();
				memoryMap->Clear(pageTable[i].physicalPage);
				pageTable[i].valid = FALSE;
			}
		}

		memoryMapLock->Release();
		return;
	}*/

	/*
		Thread 0 = main thread has
		pageTable[numPages-0*idvStackPages-1] ~ pageTable[numPages-idvStackPages*1] as its execution stack
		Thread 1 has
		pageTable[numPages-1*idvStackPages-1] ~ pageTable[numPages-idvStackPages*2]
		Thread 2 has
		pageTable[numPages-2*idvStackPages-1] ~ pageTable[numPages-idvStackPages*3]
		Thread n has
		pageTable[numpages-n*idvStackPages-1] ~ pageTable[numPages-idvStackPages*(n+1)]
		Thread MAX_THREADS-1 has
		pageTable[numPages-(MAX_THREADS-1)*idvStackPages-1] ~ pageTable[numPages - numProgramPages]
		pageTable[numPages-(MAX_THREADS-1)*idvStackPages-1] ~ pageTable[numPages - idvStackPages*MAXTHREADS]
	 */

	// allocate space for all the stack pages
	// for for MAX_THREADS all at once
	// CHANGE: to allocate just the main thread/process stack and allocate others as needed
	for (i = numPages-idvStackPages; i < numPages; i++) {
		currentValidPage = i;

		/*pageTable[i].virtualPage = i;	// for now, virtual page # = phys page #

		memoryPageID = memoryMap->Find();
		if (memoryPageID == -1) {
			memoryMapLock->Release();
			currentPageValid = FALSE;
			printf("[ERROR] NO MORE MEMORY...\n");
			//interrupt->Halt();
			//return;
			break;
		}
	
		pageTable[i].physicalPage = memoryPageID;
		pageTable[i].valid = TRUE;*/
		pageTable[i].valid = FALSE;
		pageTable[i].use = FALSE;
		pageTable[i].dirty = FALSE;
		pageTable[i].readOnly = FALSE;
		pageTable[i].location = NOT_ON_DISK;

		/*******************************Project3 step2 IPT**************************************
		iptLock->Acquire();
		
			
			ipt[pageTable[i].physicalPage].physicalPage = pageTable[i].physicalPage;
			ipt[pageTable[i].physicalPage].virtualPage = pageTable[i].virtualPage;
			ipt[pageTable[i].physicalPage].valid= TRUE;
			ipt[pageTable[i].physicalPage].iptSpace = this;
			//printf("address space : ipt ppn:%d,vpn:%d i:%d \n",ipt[pageTable[i].physicalPage].physicalPage,pageTable[i].virtualPage,i);
			
		iptLock->Release();
	/*******************************end Project3 step2 IPT**********************************/
		//bzero out the current physical memory page
		//bzero(&(machine->mainMemory[PageSize*memoryPageID]), PageSize);
	}

	// same, deallocate the pages we have allocated so far
	/*if (currentPageValid == FALSE) {
		for (i = 0; i < numProgramPages; i++) {
			if (pageTable[i].valid) {
				iptLock->Acquire();
				ipt[pageTable[i].physicalPage].valid= FALSE;
				iptLock->Release();
				memoryMap->Clear(pageTable[i].physicalPage);
				pageTable[i].valid = FALSE;
			}
		}

		for (i = numPages-idvStackPages; i < currentValidPage; i++) {
			if (pageTable[i].valid) {
				iptLock->Acquire();
				ipt[pageTable[i].physicalPage].valid= FALSE;
				iptLock->Release();
				memoryMap->Clear(pageTable[i].physicalPage);
				pageTable[i].valid = FALSE;
			}
		}

		memoryMapLock->Release();
		return;
	}*/

	//memoryMapLock->Release();



	validPageTable = TRUE;
}

//----------------------------------------------------------------------
// AddrSpace::~AddrSpace
//
// 	Dealloate an address space.  release pages, page tables, files
// 	and file tables
//----------------------------------------------------------------------

AddrSpace::~AddrSpace()
{
	unsigned int i;

	memoryMapLock->Acquire();
	if (pageTable != NULL) {
		for (i = 0; i < numPages; i++) {
			if (pageTable[i].valid) {
				memoryMap->Clear(pageTable[i].physicalPage);
			}
		}
	}
	memoryMapLock->Release();

    delete pageTable;
}

//----------------------------------------------------------------------
// AddrSpace::InitRegisters
// 	Set the initial values for the user-level register set.
//
// 	We write these directly into the "machine" registers, so
//	that we can immediately jump to user code.  Note that these
//	will be saved/restored into the currentThread->userRegisters
//	when this thread is context switched out.
//----------------------------------------------------------------------

void
AddrSpace::InitRegisters()
{
    int i;

    for (i = 0; i < NumTotalRegs; i++)
	machine->WriteRegister(i, 0);

    // Initial program counter -- must be location of "Start"
    machine->WriteRegister(PCReg, 0);	

    // Need to also tell MIPS where next instruction is, because
    // of branch delay possibility
    machine->WriteRegister(NextPCReg, 4);

   // Set the stack register to the end of the address space, where we
   // allocated the stack; but subtract off a bit, to make sure we don't
   // accidentally reference off the end!
    machine->WriteRegister(StackReg, numPages * PageSize - 16);
    DEBUG('a', "Initializing stack register to %x\n", numPages * PageSize - 16);
}

//----------------------------------------------------------------------
// AddrSpace::SaveState
// 	On a context switch, save any machine state, specific
//	to this address space, that needs saving.
//
//	For now, nothing!
//----------------------------------------------------------------------

void AddrSpace::SaveState() 
{
	IntStatus oldLevel = interrupt->SetLevel(IntOff);

	for(int i=0;i<TLBSize;i++){
		if(machine->tlb[i].valid==TRUE){		//if a tlb entry is being used by the machine
			machine->tlb[i].valid=FALSE;		//release it.
			if(machine->tlb[i].dirty==TRUE)		//check the dirty bit	
				ipt[machine->tlb[i].physicalPage].dirty==TRUE;	//populate it to the IPT
			ipt[machine->tlb[i].physicalPage].use==FALSE;	//free these IPT entries.
		}
	}
	
	(void) interrupt->SetLevel(oldLevel);
}	

//----------------------------------------------------------------------
// AddrSpace::RestoreState
// 	On a context switch, restore the machine state so that
//	this address space can run.
//
//      For now, tell the machine where to find the page table.
//----------------------------------------------------------------------

void AddrSpace::RestoreState() 
{
    //machine->pageTable = pageTable;
    machine->pageTableSize = numPages;
}

	/*
		Thread 0 = main thread has
		pageTable[numPages-0*idvStackPages-1] ~ pageTable[numPages-idvStackPages*1] as its execution stack
		Thread 1 has
		pageTable[numPages-1*idvStackPages-1] ~ pageTable[numPages-idvStackPages*2]
		Thread 2 has
		pageTable[numPages-2*idvStackPages-1] ~ pageTable[numPages-idvStackPages*3]
		Thread n has
		pageTable[numpages-n*idvStackPages-1] ~ pageTable[numPages-idvStackPages*(n+1)]
		Thread MAX_THREADS-1 has
		pageTable[numPages-(MAX_THREADS-1)*idvStackPages-1] ~ pageTable[numPages - numProgramPages]
		pageTable[numPages-(MAX_THREADS-1)*idvStackPages-1] ~ pageTable[numPages - idvStackPages*MAXTHREADS]
	 */

unsigned int
AddrSpace::getStackPointer(int threadID) {
	// we minus 16 hack since NACHOS seems to have a problem if we give it the last byte pointer, just like InitRegisters()
	// to be on the safe side
	return (totalSize - (threadID * stackSize) - 16);
}

bool
AddrSpace::createStack(int threadID) {
	unsigned int i;

	unsigned int currentValidPage;
	bool currentPageValid;

	int memoryPageID;

	currentValidPage = numPages - (threadID+1)*idvStackPages;
	currentPageValid = TRUE;

	//memoryMapLock->Acquire();

	// try to allocate all the memory space needed for the stack
	for (i = (numPages - (threadID+1)*idvStackPages); i < (numPages - threadID*idvStackPages); i++) {
		currentValidPage = i;

		pageTable[i].virtualPage = i;	// for now, virtual page # = phys page #

		/*memoryPageID = memoryMap->Find();
		if (memoryPageID == -1) {
			//memoryMapLock->Release();
			currentPageValid = FALSE;
			printf("[ERROR] NO MORE MEMORY...\n");
			//interrupt->Halt();
			//return;
			break;
		}
	
		pageTable[i].physicalPage = memoryPageID;
		pageTable[i].valid = TRUE;*/
		pageTable[i].valid = FALSE;
		pageTable[i].use = FALSE;
		pageTable[i].dirty = FALSE;
		pageTable[i].readOnly = FALSE;
	}

	// if we weren't able to allocate all the memory space needed for this stack, we release all the ones
	// we have allocated and return FALSE
	/*if (currentPageValid == FALSE) {
		for (i = (numPages - (threadID+1)*idvStackPages); i < currentValidPage; i++) {
			if (pageTable[i].valid) {
				memoryMap->Clear(pageTable[i].physicalPage);
				pageTable[i].valid = FALSE;
			}
		}

		memoryMapLock->Release();
		return FALSE;
	}*/

	//memoryMapLock->Release();
	/*******************************Project3 step2 IPT**************************************
	iptLock->Acquire();
	for(i = (numPages - (threadID+1)*idvStackPages); i < (numPages - threadID*idvStackPages); i++)
	{
		
		ipt[pageTable[i].physicalPage].physicalPage = pageTable[i].physicalPage;
		ipt[pageTable[i].physicalPage].virtualPage = i;
		ipt[pageTable[i].physicalPage].valid= TRUE;
		ipt[pageTable[i].physicalPage].iptSpace = this;
		
	}
	iptLock->Release();
	/*******************************end Project3 step2 IPT**********************************/

	return TRUE;
}

bool
AddrSpace::destroyStack(int threadID) {
	unsigned int i;

	memoryMapLock->Acquire();
	
	for (i = (numPages - (threadID+1)*idvStackPages); i < (numPages - threadID*idvStackPages); i++) {
		if (pageTable[i].valid) {
			iptLock->Acquire();
			ipt[pageTable[i].physicalPage].valid= FALSE;
			iptLock->Release();
			memoryMap->Clear(pageTable[i].physicalPage);
			pageTable[i].valid = FALSE;
			
		}
	}
	
	memoryMapLock->Release();

	
	
	return TRUE;
}

unsigned int
AddrSpace::getCodeSize() {
	return codeSize;
}

unsigned int
AddrSpace::getppn(unsigned int vpn){
	return pageTable[vpn].physicalPage;
}

